package models

import (
	"github.com/google/uuid"
	"gorm.io/gorm"
	"takeout-ordering/common/initialize"
	takeout "takeout-ordering/common/proto"
)

type User struct {
	gorm.Model
	Mobile   string `gorm:"type:char(11);not null;index:ip_idx commit:'用户电话'"`
	Password string `gorm:"type:varchar(32);not null;index:ip_idx commit:'用户密码'"`
	Points   int64  `gorm:"type:int;not null;index:ip_idx commit:'用户积分'"`
}

func (u User) FindUserMobile(mobile string) (user *User, err error) {
	err = initialize.DB.Where("mobile=?", mobile).Take(&user).Error
	if err != nil {
		return nil, err
	}
	return
}

func (u User) CreateUser(in *takeout.UserRegisterReq) (user *User, err error) {
	user = &User{
		Mobile:   in.Mobile,
		Password: in.Password,
	}
	err = initialize.DB.Create(&user).Error
	if err != nil {
		return nil, err
	}
	return

}

func (u User) FindUserMobiles(id int64) (user *User, err error) {
	err = initialize.DB.Where("id=?", id).Take(&user).Error
	if err != nil {
		return nil, err
	}
	return
}

func (u User) Updatepoints(id int64, points int64) (user *User, err error) {
	err = initialize.DB.Model(&User{}).Where("id=?", id).Update("points", points).Error
	if err != nil {
		return nil, err
	}
	return
}

type Meals struct {
	gorm.Model
	Name  string  `gorm:"type:varchar(10);not null;index:ip_idx commit:'餐品名称'"`
	Price float64 `gorm:"type:decimal(10,2);not null;index:ip_idx commit:'餐品价格'"`
	Stock int64   `gorm:"type:int;not null;index:ip_idx commit:'餐品库存'"`
	Types int64   `gorm:"type:int;not null;index:ip_idx commit:'活动种类 1:精品推荐 2:人气热卖 3:精选套餐'"`
	Img   string  `gorm:"type:varchar(255);not null;index:ip_idx commit:'餐品图片'"`
}

func (m Meals) FindMealsList() (meals []*Meals, err error) {
	err = initialize.DB.Find(&meals).Error
	if err != nil {
		return nil, err
	}
	return
}

func (m Meals) FindMealsLists(types int64) (meals []*Meals, err error) {
	err = initialize.DB.Where("types=?", types).Find(&meals).Error
	if err != nil {
		return nil, err
	}
	return
}

func (m Meals) FindMeals(id int64) (meals *Meals, err error) {
	err = initialize.DB.Where("id=?", id).Take(&meals).Error
	if err != nil {
		return nil, err
	}
	return
}

type Order struct {
	gorm.Model
	MealsId  int64   `gorm:"type:int;not null;index:ip_idx commit:'餐品ID'"`
	UserId   int64   `gorm:"type:int;not null;index:ip_idx commit:'用户ID'"`
	CouponId int64   `gorm:"type:int;not null;index:ip_idx commit:'优惠卷ID'"`
	OrderSn  string  `gorm:"type:varchar(100);not null;index:ip_idx commit:'订单编号'"`
	Sum      int64   `gorm:"type:int;not null;index:ip_idx commit:'订单数量'"`
	Price    float64 `gorm:"type:decimal(10,2);not null;index:ip_idx commit:'订单价格'"`
	Notes    string  `gorm:"type:varchar(20);not null;index:ip_idx commit:'用户备注'"`
	Status   int64   `gorm:"type:int;not null;index:ip_idx commit:'订单状态 0:未支付 1:已支付 2:已过期'"`
	Pay      int64   `gorm:"type:int;not null;index:ip_idx commit:'支付方式 1:支付宝 2:微信'"`
}

func (o Order) CreateOrder(in *takeout.CreateOrderReq, meals *Meals, stock int64, minus float32) (order *Order, err error) {
	orderSn := uuid.New().String()
	order = &Order{
		MealsId:  in.MealsId,
		UserId:   in.UserId,
		CouponId: in.CouponId,
		OrderSn:  orderSn,
		Sum:      in.Num,
		Price:    float64(in.Num)*meals.Price - float64(minus),
		Notes:    in.Notes,
		Pay:      in.Pay,
	}
	tx := initialize.DB.Begin()
	// 注意，一旦你在一个事务中，使用tx作为数据库句柄

	if err = tx.Create(&order).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	if err = tx.Model(&meals).Where("id=?", in.MealsId).Update("stock", stock).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	if err = tx.Model(&UserCoupon{}).Where("user_id=? AND c_id=?", in.UserId, in.CouponId).Update("status", 1).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()
	return
}

func (o Order) CreateOrders(in *takeout.CreateOrderReq, meals *Meals, stock int64) (order *Order, err error) {
	orderSn := uuid.New().String()
	order = &Order{
		MealsId:  in.MealsId,
		UserId:   in.UserId,
		CouponId: in.CouponId,
		OrderSn:  orderSn,
		Sum:      in.Num,
		Price:    float64(in.Num) * meals.Price,
		Notes:    in.Notes,
		Pay:      in.Pay,
	}
	tx := initialize.DB.Begin()
	// 注意，一旦你在一个事务中，使用tx作为数据库句柄

	if err = tx.Create(&order).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	if err = tx.Model(&meals).Where("id=?", in.MealsId).Update("stock", stock).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()
	return
}

func (o Order) FindOrder(id int64) (order *Order, err error) {
	err = initialize.DB.Where("id=?", id).Find(&order).Error
	if err != nil {
		return nil, err
	}
	return
}

func (o Order) UpdateStatus(sn string, status int64) (order *Order, err error) {
	err = initialize.DB.Model(&Order{}).Where("order_sn=?", sn).Update("status", status).Error
	if err != nil {
		return nil, err
	}
	return
}

func (o Order) FindOrderSn(sn string) (order *Order, err error) {
	err = initialize.DB.Model(&Order{}).Where("order_sn=?", sn).Take(&order).Error
	if err != nil {
		return nil, err
	}
	return
}

func (o Order) FindOrders(id int64) (order []*Order, err error) {
	err = initialize.DB.Where("user_id=?", id).Order("status").Find(&order).Error
	if err != nil {
		return nil, err
	}
	return
}

type Coupon struct {
	gorm.Model
	Name      string  `gorm:"type:varchar(20);not null;index:ip_idx commit:'优惠卷名称'"`
	StartTime string  `gorm:"type:datetime;not null;index:ip_idx commit:'开始时间'"`
	EndTime   string  `gorm:"type:datetime;not null;index:ip_idx commit:'结束时间'"`
	Full      float64 `gorm:"type:decimal(10,2);not null;index:ip_idx commit:'使用门槛'"`
	Minus     float64 `gorm:"type:decimal(10,2);not null;index:ip_idx commit:'优惠金额'"`
}

func (c Coupon) FindUserCouPon(id int64, id2 int64) (coupon *takeout.UserCouPon, err error) {

	err = initialize.DB.Raw("SELECT * FROM coupons JOIN user_coupons ON coupons.id=user_coupons.c_id WHERE user_coupons.user_id=? AND user_coupons.c_id=?", id, id2).Scan(&coupon).Error
	if err != nil {
		return nil, err
	}

	return coupon, err
}

func (c Coupon) FindUserCouPons(id int64) (coupon []*takeout.UserCouPon, err error) {
	err = initialize.DB.Raw("SELECT * FROM coupons JOIN user_coupons ON coupons.id=user_coupons.c_id WHERE user_coupons.user_id=?", id).Scan(&coupon).Error
	if err != nil {
		return nil, err
	}

	return coupon, err
}

type UserCoupon struct {
	gorm.Model
	CId    int64 `gorm:"type:int;not null;index:ip_idx commit:'优惠卷ID'"`
	UserId int64 `gorm:"type:int;not null;index:ip_idx commit:'用户ID'"`
	Status int64 `gorm:"type:int;not null;index:ip_idx commit:'使用状态 0:待使用 1:已使用'"`
}

func (c UserCoupon) CreateCoupon(in *takeout.CouPonReceiveReq) (user *UserCoupon, err error) {
	user = &UserCoupon{
		CId:    in.CouPonId,
		UserId: in.UserId,
	}
	err = initialize.DB.Create(&user).Error
	if err != nil {
		return nil, err
	}
	return
}
